import { Message } from "element-ui";
import { isString, isArray } from "is-type-data";
import eventCallbacks from "../eventCallbacks";

const generateInputCallback = (form, field) => {
  return (value) => {
    form[field] = value;
  };
};

const getCustomEventCallback = (event) => {
  let executor = () => {};
  const { name } = event.executor;
  if (Array.isArray(name)) {
    name.forEach((item, i) => {
      if (i === 0) {
        executor = eventCallbacks[item];
      } else {
        executor = executor[item];
      }
    });
  } else {
    executor = eventCallbacks["service"];
  }

  return executor;
};

export const loopNodeTemplateName = (VNode, targetTag = "el-form") => {
  const { tag, config, children } = VNode;
  if (tag === targetTag) {
    return config.props.templateName;
  }
  if (Array.isArray(children) && children.length > 0) {
    for (let index = 0; index < children.length; index++) {
      const element = children[index];
      return loopNodeTemplateName(element);
    }
  }
};

const isDisabled = (disabled, form) => {
  const { relation, logic = "or" } = disabled || {};
  if (relation && Array.isArray(relation) && relation.length > 0) {
    if (logic === "and") {
      return !relation.every((item) => form[item.field]);
    }
    if (logic === "or") {
      return !relation.some((item) => form[item.field]);
    }
  }

  return false;
};

const renderStringData = (str, data) => {
  if (!data) return str;
  return str.replace(/\${\w+}/g, (m) => {
    const value = data[m.slice(2, -1)];
    return value;
  });
};

export const create = function (schema, h, parentData) {
  const { tag, config, children, events, disabled, autowireConfig } = schema;
  let { data } = schema;
  if (!data) {
    data = {};
  }

  if (parentData) {
    data = { ...parentData, ...data };
  }

  if (tag === "el-table") {
    // config.props.data = source
  }
  const scopedSlots = config && config.scopedSlots;
  if (scopedSlots) {
    for (let key in scopedSlots) {
      const schema = scopedSlots[key];
      scopedSlots[key] = (props) => create.call(this, schema, h, props);
    }
  }

  if (isArray(events)) {
    events.forEach((event) => {
      if (!config.on) {
        config.on = {};
      }

      const { eventName } = event;
      config.on[eventName] = async () => {
        const fn = getCustomEventCallback(event);
        return fn.call(this, event.executor.params);
      };
    });
  }

  if (children && Array.isArray(children) && children.length) {
    const creates = children.map((child) => {
      if (isString(child)) {
        return renderStringData(child, data);
      }
      return create.call(this, child, h, data);
    });
    return h(tag, config, creates);
  } else {
    return h(tag, config);
  }
};
